using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using ProjectEuler.Core.Helpers;

namespace ProjectEuler.Core
{
    public class Problem57 : IProjectEulerProblem
    {
        protected int GetTopHeavyExpansions()
        {
            return Expansions().Count(expansion => expansion.Numerator.ToString().Length > expansion.Denominator.ToString().Length);
        }

        protected IEnumerable<Fraction> Expansions()
        {
            yield return new Fraction(3, 2);
            int i = 0;
            while(i < 1000)
            {
                var frac = new Fraction(1, 2);
                for(int j=0;j<=i;j++)
                {
                    frac.AddTo(2);
                    frac.Reciprocate();
                }
                frac.AddTo(1);
                yield return frac;
                i++;
            }
        }

        public int Number
        {
            get { return 57; }
        }

        public string Description
        {
            get { return "In the first one-thousand expansions, how many fractions contain a numerator with more digits than denominator?"; }
        }

        public string Answer
        {
            get { return GetTopHeavyExpansions().ToString(); }
        }
    }

    [TestFixture]
    public class Problem57Tests : Problem57
    {
        [Test]
        public void Then_first_expansion_is_3_over_2()
        {
            var frac = Expansions().First();
            Assert.AreEqual(3, frac.NumeratorLong);
            Assert.AreEqual(2, frac.DenominatorLong);
        }

        [Test]
        public void Then_second_expansion_is_7_over_5()
        {
            var frac = Expansions().Skip(1).Take(1).Single();
            Assert.AreEqual(7, frac.NumeratorLong);
            Assert.AreEqual(5, frac.DenominatorLong);
        }
        
        [Test]
        public void Then_third_expansion_is_17_over_12()
        {
            var frac = Expansions().Skip(2).Take(1).Single();
            Assert.AreEqual(17, frac.NumeratorLong);
            Assert.AreEqual(12, frac.DenominatorLong);
        }
        
        [Test]
        public void Then_fourth_expansion_is_41_over_29()
        {
            var frac = Expansions().Skip(3).Take(1).Single();
            Assert.AreEqual(41, frac.NumeratorLong);
            Assert.AreEqual(29, frac.DenominatorLong);
        }

        [Test]
        public void Then_fifth_expansion_is_99_over_70()
        {
            var frac = Expansions().Skip(4).Take(1).Single();
            Assert.AreEqual(99, frac.NumeratorLong);
            Assert.AreEqual(70, frac.DenominatorLong);
        }

        [Test]
        public void Then_fifth_expansion_is_239_over_169()
        {
            var frac = Expansions().Skip(5).Take(1).Single();
            Assert.AreEqual(239, frac.NumeratorLong);
            Assert.AreEqual(169, frac.DenominatorLong);
        }

        [Test]
        public void Then_sixth_expansion_is_577_over_408()
        {
            var frac = Expansions().Skip(6).Take(1).Single();
            Assert.AreEqual(577, frac.NumeratorLong);
            Assert.AreEqual(408, frac.DenominatorLong);
        }

        [Test]
        public void Then_eigth_expansion_is_1393_over_985()
        {
            var frac = Expansions().Skip(7).Take(1).Single();
            Assert.AreEqual(1393, frac.NumeratorLong);
            Assert.AreEqual(985, frac.DenominatorLong);
        }
    }
}